package org.xiaodongwei.jvm.op;

import org.xiaodongwei.jvm.exe.JVMStack;
import org.xiaodongwei.jvm.utils.ObjectUtils;
import tech.medivh.classpy.classfile.bytecode.Instruction;
import tech.medivh.classpy.classfile.constant.ConstantPool;
import tech.medivh.classpy.classfile.jvm.Opcode;

/**
 * 在 JVM规范 中，fcmpl指令的具体行为如下：
 * ‌操作数栈‌：
 *      该指令会弹出栈顶的两个float值进行比较。
 * ‌结果‌：
 *      比较结果（0、1或-1）会被压入栈中。如果两个值相等，压入0；
 *      如果第一个值大于第二个值，压入1；如果第一个值小于第二个值，压入-1。
 */

public class FCmplOpCodeExecute extends OpCodeExecute {

    public FCmplOpCodeExecute(JVMStack jvmStack, ConstantPool constantPool) {
        this.opCode = Opcode.fcmpg;
        this.jvmStack = jvmStack;
        this.constantPool = constantPool;
    }

    @Override
    public void execute(Instruction instruction) {
        Object value2 = jvmStack.peek().getOperateStack().pop();
        Object value1 = jvmStack.peek().getOperateStack().pop();

        if (ObjectUtils.isSameType(value1, value2)) {
            String simpleClassName = value1.getClass().getSimpleName();

            // 变量顺序保持和栈中顺序一致：栈顶往下的顺序
            switch (simpleClassName) {
                case "Integer" -> {
                    Integer v2 = ObjectUtils.toInteger(value2);
                    Integer v1 = ObjectUtils.toInteger(value1);
                    jvmStack.peek().getOperateStack().push(v1.compareTo(v2));
                }
                case "Long" -> {
                    Long v2 = ObjectUtils.toLong(value2);
                    Long v1 = ObjectUtils.toLong(value1);
                    jvmStack.peek().getOperateStack().push(v1.compareTo(v2));
                }
                case "Float" -> {
                    Float v2 = ObjectUtils.toFloat(value2);
                    Float v1 = ObjectUtils.toFloat(value1);
                    jvmStack.peek().getOperateStack().push(v1.compareTo(v2));
                }
                default -> {
                    throw new IllegalArgumentException("Data types currently not supported");
                }
            }
        }
    }
}
